package com.hnichr.ump.api.controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hnichr.ump.business.Constant;
import com.hnichr.ump.common.doc.entity.Banner;
import com.hnichr.ump.common.doc.entity.Goods;
import com.hnichr.ump.common.doc.entity.GoodsType;
import com.hnichr.ump.common.doc.entity.Order;
import com.hnichr.ump.common.doc.entity.OrderLog;
import com.hnichr.ump.common.doc.service.BannerService;
import com.hnichr.ump.common.doc.service.GoodsService;
import com.hnichr.ump.common.doc.service.GoodsTypeService;
import com.hnichr.ump.common.doc.service.OrderLogService;
import com.hnichr.ump.common.doc.service.OrderService;
import com.hnichr.ump.common.doc.service.WeChatService;
import com.hnichr.ump.common.vo.CreateOrderVo;
import com.hnichr.ump.common.vo.wechat.PhoneInfoRespVo;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.filestorage.entity.MxpioFileInfo;
import com.mxpioframework.filestorage.service.FileStorageService;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Tag(name = "DocController", description = "文印商城小程序相关接口")
@RestController
@RequestMapping("/api/doc/v1")
public class DocController {

	@Autowired
	private WeChatService weChatService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private OrderLogService orderLogService;
	@Autowired
	private BannerService bannerService;
	@Autowired
	private GoodsService goodsService;
	@Autowired
	private GoodsTypeService goodsTypeService;
	@Autowired
	private FileStorageService fileStorageService;

	@Value("${minio.resUrl}")
	private String restUrl;

	/**
	 * 获取openId
	 *
	 * @param code 授权码
	 * @return openId
	 */
	@GetMapping("/getOpenId")
	@Operation(summary = "获取openId", description = "获取openId", method = "GET")
	public Result<Map<String, Object>> getOpenId(@RequestParam("code") String code) {
		if (StringUtils.isBlank(code)) {
			return Result.error("code不能为空！");
		}
		log.info("DocController getOpenId code：" + code);
		// 获取openId
		String openId = weChatService.getOpenId(code);
		if (Objects.isNull(openId)) {
			return Result.error("获取openId失败");
		}
		Map<String, Object> result = new HashMap<>();
		result.put("openId", openId);
		return Result.OK(result);
	}

	/**
	 * 获取用户手机号
	 *
	 * @param code 授权码
	 * @return 手机号
	 */
	@GetMapping("/getPhoneNumber")
	@Operation(summary = "获取手机号", description = "获取手机号", method = "GET")
	public Result<Map<String, Object>> getPhoneNumber(@RequestParam("code") String code) {
		if (StringUtils.isBlank(code)) {
			return Result.error("code不能为空！");
		}
		log.info("DocController getPhoneNumber code：" + code);
		// 获取accessToken
		String accessToken = weChatService.getAccessToken();
		if (StringUtils.isEmpty(accessToken)) {
			return Result.error("获取accessToken失败");
		}
		// 获取手机号
		PhoneInfoRespVo phoneInfo = weChatService.getPhoneInfo(accessToken, code);
		if (Objects.isNull(phoneInfo)) {
			return Result.error("获取手机号失败");
		}
		String phoneNum = phoneInfo.getPhone_info().getPhoneNumber();
		Map<String, Object> result = new HashMap<>();
		result.put("phoneNum", phoneNum);
		return Result.OK(result);
	}

	/**
	 * 推送消息（仅用于测试）
	 *
	 * @param param 参数
	 * @return openId
	 */
	@PostMapping("/sendMessage")
	@Operation(summary = "推送消息", description = "推送消息", method = "POST")
	public Result<JSONObject> sendMessage(@RequestBody String param) {
		if (StringUtils.isBlank(param)) {
			return Result.error("参数不能为空！");
		}
		log.info("DocController sendMessage param：" + param);
		JSONObject obj = JSONUtil.parseObj(param);
		String openId = obj.getStr("openId");
		String orderId = obj.getStr("orderId");
		String bizType = obj.getStr("bizType");
		String orderNo = obj.getStr("orderNo");
		// 推送消息
		JSONObject jsonObject = weChatService.sendMessage(openId, orderId, orderNo, bizType);
		if (Objects.isNull(jsonObject)) {
			return Result.error("推送消息失败");
		}
		return Result.OK(jsonObject);
	}

	/**
	 * 保存订单信息
	 *
	 * @param createOrderVo 订单信息
	 * @return
	 */
	@PostMapping("/createOrder")
	@Operation(summary = "保存订单信息", description = "保存订单信息", method = "POST")
	public Result<Map<String, Object>> createOrder(@RequestBody @Valid CreateOrderVo createOrderVo) {
		log.info("DocController createOrder createOrderVo：" + JSONUtil.toJsonStr(createOrderVo));
		// 参数校验
		if (Integer.parseInt(createOrderVo.getBizType()) < Integer.parseInt(Constant.DOC_BIZ_TYPE_10)
				|| Integer.parseInt(createOrderVo.getBizType()) > Integer.parseInt(Constant.DOC_BIZ_TYPE_50)) {
			return Result.error("业务类型不合法");
		}
		// 保存订单信息
		String orderNo = orderService.createOrder(createOrderVo);
		Map<String, Object> result = new HashMap<>();
		result.put("orderId", orderNo);
		return Result.OK(result);
	}

	/**
	 * 计算预报价
	 *
	 * @param createOrderVo 订单信息
	 * @return
	 */
	@PostMapping("/calcPrePrice")
	@Operation(summary = "计算预报价", description = "计算预报价", method = "POST")
	public Result<Map<String, Object>> calcPrePrice(@RequestBody CreateOrderVo createOrderVo) {
		log.info("DocController calcPrePrice createOrderVo：" + JSONUtil.toJsonStr(createOrderVo));
		// 参数校验
		if (Integer.parseInt(createOrderVo.getBizType()) < Integer.parseInt(Constant.DOC_BIZ_TYPE_10)
				|| Integer.parseInt(createOrderVo.getBizType()) > Integer.parseInt(Constant.DOC_BIZ_TYPE_50)) {
			return Result.error("业务类型不合法");
		}
		// 计算预报价
		double prePrice = orderService.calcPrePrice(createOrderVo);
		// 特殊处理
		BigDecimal bigDecimal = new BigDecimal(prePrice).setScale(2, RoundingMode.HALF_UP);
		String prePriceStr = bigDecimal.toPlainString();
//		if (Constant.DOC_BIZ_TYPE_40.equals(createOrderVo.getBizType())
//			|| Constant.DOC_BIZ_TYPE_50.equals(createOrderVo.getBizType())) {
//			prePriceStr = "最低" + bigDecimal.toPlainString();
//		}
		Map<String, Object> result = new HashMap<>();
		result.put("prePrice", prePriceStr);
		return Result.OK(result);
	}

	/**
	 * 获取订单预览图
	 *
	 * @param fileNo
	 * @param response
	 * @return
	 */
	@GetMapping("/getPreviewImage")
	@Operation(summary = "获取订单预览图", description = "获取订单预览图", method = "GET")
	public Result<String> getPreviewImage(@RequestParam("fileNo") String fileNo, HttpServletResponse response) {
		if (StringUtils.isBlank(fileNo)) {
			return Result.error("fileNo不能为空！");
		}
		try {
			MxpioFileInfo fileInfo = fileStorageService.get(fileNo);
			return Result.OK(restUrl + "/" + fileInfo.getAbsolutePath());
		} catch (Exception e) {
			log.error("获取订单预览图失败：", e);
			return Result.error("获取订单预览图失败");
		}
	}

	/**
	 * 确认订单
	 *
	 * @param orderId 订单编号
	 * @return
	 */
	@PostMapping("/confirmOrder")
	@Operation(summary = "确认订单信息", description = "确认订单信息", method = "POST")
	public Result<Void> confirmOrder(@RequestParam("orderId") String orderId) {
		if (StringUtils.isBlank(orderId)) {
			return Result.error("orderId不能为空！");
		}
		try {
			orderService.updateStatus("user", orderId, "1");
			return Result.OK();
		} catch (Exception e) {
			return Result.error(e.getMessage());
		}
	}

	/**
	 * 获取订单列表
	 *
	 * @param openId
	 * @return
	 */
	@GetMapping("/getOrders")
	@Operation(summary = "获取订单列表", description = "获取订单列表", method = "GET")
	public Result<List<Order>> getOrders(@RequestParam("openId") String openId,
			@RequestParam(value = "orderId", required = false) String orderId) {
		if (StringUtils.isBlank(openId)) {
			return Result.error("openId不能为空！");
		}
		Criteria criteria = Criteria.create();
		criteria.addCriterion("openId", Operator.EQ, openId);
		criteria.addCriterion("validFlag", Operator.EQ, Constant.STATUS_VALID);
		if (StringUtils.isNotBlank(orderId)) {
			criteria.addCriterion("orderNo", Operator.LIKE, orderId);
		}
		criteria.addOrder(new com.mxpioframework.jpa.query.Order("createTime", true));
		List<Order> orders = orderService.list(Order.class, criteria);
		// 校验不通过 处理为 已接单
		if (CollectionUtil.isNotEmpty(orders)) {
			for (Order order : orders) {
				// 30初稿已完成 31校对不通过 小程序展示为 20已接单
				if (Constant.DOC_STATUS_31.equals(order.getStatus())
						|| Constant.DOC_STATUS_30.equals(order.getStatus())) {
					order.setStatus(Constant.DOC_STATUS_20);
				}
			}
		}
		return Result.OK(orders);
	}

	/**
	 * 获取订单动态
	 *
	 * @param orderId
	 * @return
	 */
	@GetMapping("/getOrderLog")
	@Operation(summary = "获取订单动态", description = "获取订单动态", method = "GET")
	public Result<List<OrderLog>> getOrderLog(@RequestParam("orderId") String orderId) {
		if (StringUtils.isBlank(orderId)) {
			return Result.error("orderId不能为空！");
		}
		Criteria criteria = Criteria.create();
		criteria.addCriterion("orderId", Operator.EQ, orderId);
		criteria.addCriterion("appShow", Operator.EQ, Constant.STATUS_VALID);
		criteria.addOrder(new com.mxpioframework.jpa.query.Order("createTime", true));
		List<OrderLog> orderLogs = orderLogService.list(OrderLog.class, criteria);
		return Result.OK(orderLogs);
	}

	/**
	 * 获取首页商品列表
	 *
	 * @return
	 */
	@GetMapping("/getHomeGoods")
	@Operation(summary = "获取首页商品列表", description = "获取首页商品列表", method = "GET")
	public Result<Page<Goods>> getHomeGoods(@RequestParam(required = false, defaultValue = "0") int pageNo,
			@RequestParam(required = false, defaultValue = "10") int pageSize) {
		Criteria criteria = Criteria.create();
		criteria.addCriterion("homeFlag", Operator.EQ, "1");// 首页显示
		criteria.addCriterion("onlineFlag", Operator.EQ, "10");// 已上架
		criteria.addCriterion("validFlag", Operator.EQ, Constant.STATUS_VALID);// 有效
		criteria.addOrder(new com.mxpioframework.jpa.query.Order("createTime", true));
		Pageable page = PageRequest.of(pageNo, pageSize);
		Page<Goods> goods = goodsService.listPage(Goods.class, page, criteria);
		return Result.OK(goods);
	}

	/**
	 * 获取轮播图
	 *
	 * @return
	 */
	@GetMapping("/getBanners")
	@Operation(summary = "获取轮播图", description = "获取轮播图", method = "GET")
	public Result<Page<Banner>> getBanners() {
		Criteria criteria = Criteria.create();
		criteria.addOrder(new com.mxpioframework.jpa.query.Order("seqNo", true));
		Pageable page = PageRequest.of(0, 3);
		Page<Banner> banners = bannerService.listPage(Banner.class, page, criteria);
		return Result.OK(banners);
	}

	/**
	 * 获取分类列表
	 *
	 * @return
	 */
	@GetMapping("/getGoodsTypes")
	@Operation(summary = "获取分类列表", description = "获取分类列表", method = "GET")
	public Result<List<GoodsType>> getGoodsTypes() {
		Criteria criteria = Criteria.create();
		criteria.addCriterion("validFlag", Operator.EQ, Constant.STATUS_VALID);
		criteria.addOrder(new com.mxpioframework.jpa.query.Order("seqNo", false));
		List<GoodsType> goodsTypes = goodsTypeService.list(GoodsType.class, criteria);
		return Result.OK(goodsTypes);
	}

	/**
	 * 获取商品列表
	 *
	 * @param goodsType 商品分类
	 * @return
	 */
	@GetMapping("/getGoodsList")
	@Operation(summary = "获取商品列表", description = "获取商品列表", method = "GET")
	public Result<Page<Goods>> getGoodsList(@RequestParam("goodsType") String goodsType,
			@RequestParam(required = false, defaultValue = "1") int pageNo,
			@RequestParam(required = false, defaultValue = "100") int pageSize) {
		Criteria criteria = Criteria.create();
		if (StrUtil.isNotBlank(goodsType)) {
			criteria.addCriterion("goodsType", Operator.EQ, goodsType);
		}
		criteria.addCriterion("onlineFlag", Operator.EQ, "10");
		criteria.addCriterion("validFlag", Operator.EQ, Constant.STATUS_VALID);
		criteria.addOrder(new com.mxpioframework.jpa.query.Order("createTime", true));
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		Page<Goods> goodsList = goodsService.listPage(Goods.class, page, criteria);
		return Result.OK(goodsList);
	}

	/**
	 * 获取商品详情
	 *
	 * @param goodsId 商品编号
	 * @return
	 */
	@GetMapping("/getGoods")
	@Operation(summary = "获取商品详情", description = "获取商品详情", method = "GET")
	public Result<Goods> getGoods(@RequestParam("goodsId") String goodsId) {
		if (StringUtils.isBlank(goodsId)) {
			return Result.error("goodsId不能为空！");
		}
		Goods goods = goodsService.getById(Goods.class, goodsId);
		if (Objects.isNull(goods)) {
			Criteria criteria = Criteria.create();
			criteria.addCriterion("goods", Operator.EQ, goodsId);
			List<Goods> goodsList = goodsService.list(Goods.class, criteria);
			if (CollUtil.isNotEmpty(goodsList)) {
				goods = CollUtil.getFirst(goodsList);
			}
		}
		return Result.OK(goods);
	}
}
